home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / dos / prg / pas / swag / win_os2.swg / 0050_Windows Toolbar with TIP.pas < prev    next >
Pascal/Delphi Source File  |  1994-11-30  |  14KB  |  504 lines

  1. {
  2. From: chrfa@ida.liu.se (Christer Fahlgren)
  3.  
  4. For all people out there wishing a Toolbar with TIP-capabilities, I've
  5. written a TIPBAR-unit which is the basic toolbar enhanced with tip
  6. capabilities.
  7.  
  8. Since I'm no expert programmer I'd appreciate input on this.
  9. Info follows in the file included below.
  10.  
  11. {**************************************************}
  12. {                                                  }
  13. {   Turbo Pascal for Windows                       }
  14. {   Tipbar unit - a toolbar with TIP-capabilities  }
  15. {   Copyleft (cl) 1994 by Christer Fahlgren        }
  16. {                                                  }
  17. {   This source is freeware! Please (ab)use,       }
  18. {   change, include in commercial programs,        }
  19. {   throw away, WHATEVER you feel like.            }
  20. {                                                  }
  21. {   This unit was written because I thought it     }
  22. {   would be cool If I could have tooltips myself. }
  23. {   And I gathered that the best way of enhancing  }
  24. {   this unit would be to throw it out to the      }
  25. {   public programmer mob for scrutiny.            }
  26. {   I am no expert at this and It may contain      }
  27. {   errors for which I can take no respons-        }
  28. {   ibilities. However, please send me your        }
  29. {   comments, enhancements and bugs for my and     }
  30. {   your benefit.                                  }
  31. {                                                  }
  32. {   I also would like to say that I am a bit tired }
  33. {   of all the people asking for money for petty   }
  34. {   source code.                                   }
  35. {                                                  }
  36. {   The inspiration for this unit was the tooltip  }
  37. {   C++ code which I found the other day.          }
  38. {                                                  }
  39. {                                                  }
  40. {   This toolbar relies on the original toolbar    }
  41. {   which resides in the \examples\win\toolbar     }
  42. {   directory in BP7.                              }
  43. {                                                  }
  44. {   Enjoy!                                         }
  45. {                                                  }
  46. {   Christer Fahlgren                              }
  47. {   Email: chrfa@ida.liu.se                        }
  48. {   Snail: VΣstanσgatan 26A:204                    }
  49. {   S-582 35 Link÷ping                             }
  50. {   Sweden                                         }
  51. {**************************************************}
  52.  
  53. {--------------------------------------------------
  54.  Q:What do I do if I already use the toolbar unit
  55.  in Borland Pascal???
  56.  
  57.  A:First add Tipbar to your uses clause
  58.    Then add a parameter to your init statement
  59.    of your toolbar like this:
  60.    Init(ParentWin, AName, Orient) ->
  61.    Init(ParentWin, Aname, Orient, Delay) where
  62.    Delay is the delay in milliseconds for the help
  63.    to show up.
  64.  
  65.    Change occurences of TToolbar to TTipbar
  66.    Change occurences of PToolbar to PTipbar
  67.  
  68.    Lastly you have to redefine your old
  69.    ToolBarData statements with the new resource-
  70.    name HelpToolBarData. This resource looks
  71.    like the old ToolBarData but a null-terminated
  72.    string is included for every tool. This string
  73.    can maximum be 255 chars.
  74.  
  75.    Example:
  76.  
  77.    AHelpToolbar  HelpToolBarData
  78.    BEGIN
  79.          2                      (Number of tools and spacers in this resource )
  80.          tb_open                (id of a bitmap                               )
  81.          cm_open                (menu id                                      )
  82.          "Opens a file\0"       (Text which is null-terminated                )
  83.          tb_save                (id of a bitmap                               )
  84.          cm_save                (menu id                                      )
  85.          "Saves the file\0"     (Text which is null-terminated                )
  86.    END
  87.  
  88.  ----------------------------------------------------------}
  89.  
  90. {----------------------------------------------------------}
  91. {                                                          }
  92. { INFORMATION AND PRECAUTIONS                              }
  93. { ---------------------------                              }
  94. { The Store and Load methods are NOT tested!               }
  95. { It uses one timer (a scarce resource in Win 3.x)         }
  96. {                                                          }
  97. { This unit is NOT thoroughly tested and all use is at     }
  98. { your own risk, BUT it SEEMS to work well.                }
  99. {----------------------------------------------------------}
  100.  
  101. {----------------------------------------------------------}
  102. { Possible ENHANCEMENTS                                    }
  103. { ---------------------                                    }
  104. { Store the font for the popupwindow in the toolbar        }
  105. { instead of creating it each time in the HelpWindow       }
  106. { No more than one calculating of the size of the text     }
  107. { in the popupwindow.                                      }
  108. {----------------------------------------------------------}
  109.  
  110. unit TipBar;
  111.  
  112. interface
  113.  
  114. uses Winprocs, Wintypes, Objects, OWindows, Strings, Win31, toolbar;
  115.  
  116. type
  117.   PTipbar = ^TTipbar;
  118.   PTipbutton = ^TTipbutton;
  119.   PHelpWindow=^THelpWindow;
  120.  
  121.   { This is the definition to the Popupwindow which shows the tip}
  122.  
  123.   THelpWindow=object(TWindow)
  124.      LogicalFont : TLOGFONT;
  125.      ToolToHelp : PTipbutton;
  126.      constructor Init (AParent : PTipbar; Tool : PTipbutton; WherePos : TPoint;
  127. Width, Height : Word);
  128.      procedure Paint (DC : HDC; var PS : TPaintStruct); virtual;
  129.   end;
  130.  
  131.   { This is a normal toolbarbutton with an extra string variable}
  132.  
  133.   TTipbutton=object(TToolbutton)
  134.      HelpString:array[0..255] of char;
  135.   end;
  136.  
  137.   { This is the definition of our new Tipbar }
  138.  
  139.   TTipbar = object(TToolbar)
  140.     Help : Boolean;          {Decides if we should help or not}
  141.     Timer : Word;            {Timer to use}
  142.     ToolToHelp : PTipButton; {Points to the button to help, it is nil if no
  143. button needs help}
  144.     PopWin : PHelpWindow;    {Pointer to the Helpwindow if one exists}
  145.     OldMouseCoord : Tpoint;  {Helps remember the mousecoordinate}
  146.     Delay : Word;
  147.  
  148.     constructor Init(AParent : PWindow; AName : PChar; Orient : Word; Delaypar
  149. : word);
  150.     destructor done; virtual;
  151.  
  152.     constructor Load(var S: TStream);
  153.     procedure Store(var S: TStream); virtual;
  154.  
  155.     function  GetClassName: PChar; virtual;
  156.     procedure GetWindowClass(var WC: TWndClass); virtual;
  157.  
  158.     procedure ReadResource; virtual;
  159.  
  160.     procedure Timermsg(Var Msg:TMessage); virtual wm_first+wm_timer;
  161.  
  162.     procedure GetToolUnder(P:Tpoint);
  163.  
  164.     procedure WMMouseMove(var Msg: TMessage);
  165.       virtual wm_First + wm_MouseMove;
  166.  
  167.     function  CreateTool(Num: Integer; Origin: TPoint; Command: Word;
  168.       BitmapName: PChar): PTool; virtual;
  169.  
  170.     procedure EnableHelp;
  171.     procedure DisableHelp;
  172.  
  173.     procedure ChangeDelay(Delaypar:Word);
  174.   end;
  175.  
  176.  
  177.  
  178. const
  179.   RTipbar: TStreamRec = (
  180.     ObjType: 12302;
  181.     VmtLink: Ofs(TypeOf(TTipbar)^);
  182.     Load:    @TTipbar.Load;
  183.     Store:   @TTipbar.Store);
  184.  
  185. implementation
  186.  
  187.  
  188. constructor TTipbar.Init (AParent : PWindow; AName : PChar; Orient : Word;
  189. Delaypar : word);
  190. begin
  191.   inherited Init(AParent,Aname,orient);
  192.   Timer := 0;
  193.   Delay := Delaypar;
  194.   Popwin := nil;
  195.   ToolToHelp := nil;
  196.   Help := TRUE;      {Default is to show help}
  197. end;
  198.  
  199. destructor TTipbar.Done;
  200. begin
  201.   KillTimer(Hwindow,1);
  202.   inherited Done;
  203. end;
  204.  
  205. procedure TTipbar.Enablehelp;
  206. begin
  207.   Help:=TRUE;
  208. end;
  209.  
  210.  
  211. procedure TTipbar.Disablehelp;
  212. begin
  213.   Help:=FALSE;
  214. end;
  215.  
  216. procedure TTipbar.ChangeDelay(Delaypar:Word);
  217. begin
  218.   Delay:=Delaypar;
  219. end;
  220.  
  221. constructor TTipbar.Load(var S: TStream);
  222. var
  223.   X: Integer;
  224.  
  225.   procedure RestoreStates(P : PTool); far;
  226.   begin
  227.     P^.Read(S);
  228.   end;
  229.  
  230. begin
  231.   inherited Load(S);
  232.   Attr.Style := ws_Child or ws_Visible or ws_Border ;
  233.   SetFlags(wb_MDIChild, False);
  234.   DefaultProc := @DefWindowProc;
  235.   Capture := nil;
  236.   S.Read(Orientation, SizeOf(Orientation));
  237.   Tools.Init(8,8);
  238.  
  239.   ResName := nil;
  240.   S.Read(X, SizeOf(X));
  241.   if X = 0 then
  242.     S.Read(PtrRec(ResName).Ofs, SizeOf(Word))
  243.   else
  244.     ResName := S.StrRead;
  245.  
  246.   ReadResource;
  247.   if Status <> em_InvalidChild then
  248.     Tools.ForEach(@RestoreStates)
  249.   else
  250.     S.Status := stGetError;
  251. end;
  252.  
  253.  
  254. procedure TTipbar.Store(var S: TStream);
  255. var
  256.   X: Integer;
  257.  
  258.   procedure SaveStates(P : PTool); far;
  259.   begin
  260.     P^.Write(S);
  261.   end;
  262.  
  263. begin
  264.   inherited Store(S);
  265.   S.Write(Orientation, SizeOf(Orientation));
  266.   if HiWord(Longint(ResName)) <> 0 then
  267.   begin
  268.     X := 1;
  269.     S.Write(X, SizeOf(X));
  270.     S.StrWrite(ResName);
  271.   end
  272.   else
  273.   begin
  274.     X := 0;
  275.     S.Write(X, SizeOf(X));
  276.     S.Write(PtrRec(ResName).Ofs, SizeOf(Word));
  277.   end;
  278.   Tools.ForEach(@SaveStates);
  279. end;
  280.  
  281.  
  282. procedure TTipbar.ReadResource;
  283. type
  284.   ResRec = record
  285.     Bitmap,
  286.     Command: Word;
  287.   end;
  288.  
  289.   PResArray = ^TResArray;
  290.   TResArray = array [1..$FFF0 div sizeof(ResRec)] of ResRec;
  291.  
  292. var
  293.   ResIdHandle: THandle;
  294.   ResDataHandle: THandle;
  295.   ResDataPtr: PResArray;
  296.   Count: Word;
  297.   X: Word;
  298.   Origin: TPoint;
  299.   BitInfo: TBitmap;
  300.   P: PTool;
  301.  
  302. begin
  303.   ResIDHandle := FindResource(HInstance, ResName, 'HelpToolBarData');
  304.   ResDataHandle := LoadResource(HInstance, ResIDHandle);
  305.   ResDataPtr := LockResource(ResDataHandle);
  306.   if (ResIDHandle = 0) or (ResDataHandle = 0) or (ResDataPtr = nil) then
  307.   begin
  308.     Status := em_InvalidChild;
  309.     Exit;
  310.   end;
  311.  
  312.   X := 0;
  313.   Origin.X := 2;
  314.   Origin.Y := 2;
  315.  
  316.   Count := PWord(ResDataPtr)^;
  317.   Inc(LongInt(ResDataPtr), SizeOf(Count)); { Skip Count }
  318.   for X := 1 to Count do
  319.     with ResDataPtr^[1] do
  320.     begin
  321.       P := CreateTool(X, Origin, Command, PChar(Bitmap));
  322.       if P <> nil then
  323.       begin
  324.         NextToolOrigin(X, Origin, P);
  325.         Tools.Insert(P);
  326.       end;
  327.       Inc(Longint(ResDataPtr),sizeof(Resrec));
  328.  
  329.       if Bitmap<>0 then
  330.       begin
  331.         Strcopy(PTipbutton(P)^.HelpString,Pchar(Resdataptr));
  332.         inc(LongInt(ResdataPtr),strlen(PTipbutton(P)^.HelpString)+1);
  333.       end;
  334.     end;
  335.   Inc(Attr.H, 8);
  336.   Inc(Attr.W, 8);
  337.  
  338.   UnlockResource(ResDataHandle);
  339.   FreeResource(ResDataHandle);
  340. end;
  341.  
  342.  
  343. function TTipbar.CreateTool( Num : Integer; Origin : TPoint; Command : Word;
  344. BitmapName : PChar): PTool;
  345. begin
  346.   if Word(BitmapName) = 0 then
  347.     CreateTool := New(PToolSpacer, Init(@Self, Command))
  348.   else
  349.     CreateTool := New(PTipButton, Init(@Self, Origin.X, Origin.Y, Command,
  350.       BitmapName));
  351. end;
  352.  
  353.  
  354. function TTipbar.GetClassName: PChar;
  355. begin
  356.   GetClassName := 'Tipbar';
  357. end;
  358.  
  359. procedure TTipbar.GetWindowClass(var WC: TWndClass);
  360. begin
  361.   TWindow.GetWindowClass(WC);
  362.   WC.hbrBackground := GetStockObject(LtGray_Brush);
  363. end;
  364.  
  365.  
  366. procedure TTipbar.WMMouseMove(var Msg: TMessage);
  367. begin
  368.   if Popwin<>nil then
  369.   begin
  370.     if not((OldMouseCoord.x=TPoint(Msg.Lparam).x) and
  371. (OldMouseCoord.y=TPoint(Msg.Lparam).y)) then
  372.     begin
  373.       Popwin^.Done;
  374.       popwin:=NIL;
  375.     end;
  376.   end;
  377.  
  378.   If HELP then GetToolUnder(TPoint(Msg.Lparam));
  379.  
  380.   if (Capture <> nil) then
  381.     Capture^.ContinueCapture(TPoint(Msg.LParam));
  382. end;
  383.  
  384. procedure TTipbar.GetToolUnder(P:TPoint);
  385.   function IsUnder(Item:PTool):boolean; far;
  386.   begin
  387.     IsUnder := Item^.HitTest(P);
  388.   end;
  389. begin
  390.   ToolToHelp := Tools.firstThat(@IsUnder);
  391.   if ToolToHelp <> nil then
  392.   begin
  393.     SetTimer( Hwindow, 1, Delay, nil);
  394.     OldMouseCoord.x := P.x;
  395.     OldMouseCoord.y := P.y;
  396.   end;
  397. end;
  398.  
  399. procedure TTipbar.Timermsg(Var Msg:TMessage);
  400. var Co : Tpoint;
  401. begin
  402.   GetCursorPos(Co);
  403.   ScreenToClient(Hwindow,Co);
  404.   GetToolUnder(Co);
  405.   if (PopwIN = nil) and (ToolToHelp <> nil) then
  406.   begin
  407.     co.x := OldMouseCoord.x;
  408.     co.y := OldMouseCoord.y;
  409.     ClientToScreen(Hwindow,Co);
  410.     Popwin := new(PHelpWindow,Init(@self,ToolToHelp,Co,10,10));
  411.     Application^.MakeWindow(Popwin);
  412.     ShowWindow(Popwin^.HWindow,SW_SHOWNOACTIVATE);
  413.     KillTimer(Hwindow,1);
  414.   end;
  415. end;
  416.  
  417. constructor THelpWindow.Init(AParent : PTipbar; Tool : PTipbutton; WherePos :
  418. TPoint; Width, Height : Word);
  419. var Odc:HDC;
  420.     Rect:TRect;
  421.     Font,OldFont:HFONT;
  422. begin
  423.   with LogicalFont do
  424.   begin
  425.     lfHeight        := 14;
  426.     lfWidth         := 0;
  427.     lfEscapement    := 0;
  428.     lfOrientation   := 0;
  429.     lfWeight        := FW_NORMAL;
  430.     lfItalic        := 0;
  431.     lfUnderline     := 0;
  432.     lfStrikeOut     := 0;
  433.     lfCharSet       := ANSI_CharSet;
  434.     lfOutPrecision  := Out_Default_Precis;
  435.     lfClipPrecision := Clip_Default_Precis;
  436.     lfQuality       := Proof_Quality;
  437.     lfPitchAndFamily:= Variable_Pitch or FF_Roman;
  438.     StrCopy(lfFaceName,'Arial');
  439.   end;
  440.   inherited Init(Aparent,nil);
  441.  
  442.   ToolToHelp := Tool;
  443.  
  444.   { Firstly, we will position the window att the x coordinate of the cursor and
  445. 10 pixels below the y}
  446.  
  447.   attr.x := Wherepos.x;
  448.   attr.y := Wherepos.y+10;
  449.  
  450.   { Then, we calculate the height of the text but we set the maximum width to
  451. be 70 pixels}
  452.  
  453.   setRect(Rect,0,0,70,0);
  454.  
  455.   font := CreateFontIndirect(LogicalFont);
  456.   Odc := GetDC(0);
  457.   OldFont := Selectobject(odc,font);
  458.   Drawtext(ODc, ToolToHelp^.HelpString, strlen(ToolToHelp^.HelpString), Rect,
  459. DT_LEFT or DT_CALCRECT or DT_WORDBREAK);
  460.  
  461.   {Now, we have the width and height of the text in Rect. Then we add a bit to
  462. center the text. }
  463.  
  464.   Attr.w := Rect.right+10;
  465.   Attr.h := Rect.bottom+10;
  466.  
  467.   Selectobject(odc,OldFont);
  468.   Deleteobject(Font);
  469.   ReleaseDC(0,Odc);
  470.  
  471.   { The style is pretty important}
  472.  
  473.   Attr.Style := ws_border or ws_popup or ws_disabled ;
  474.  
  475. end;
  476.  
  477. procedure THelpWindow.Paint(DC: HDC; var PS: TPaintStruct);
  478.  
  479. var Rect:TRect;
  480.     Font,OldFont:HFONT;
  481.  
  482. begin
  483.  
  484.   {First, we measure again the size of the text, unnecessary this should be
  485. stored in an instance variable}
  486.   {instead. A future enhancement.}
  487.  
  488.   setRect(Rect,0,0,70,0);
  489.   Font := CreateFontIndirect(LogicalFont);
  490.   OldFont := Selectobject(dc,font);
  491.   Drawtext(DC, ToolToHelp^.HelpString,strlen(ToolToHelp^.HelpString),Rect
  492. DT_LEFT or DT_CALCRECT or DT_WORDBREAK);
  493.  
  494.   OffsetRect(Rect,5,5);
  495.  
  496.   Drawtext(DC,ToolToHelp^.HelpString,strlen(ToolToHelp^.HelpString),Rect
  497. DT_LEFT or DT_WORDBREAK );
  498.   SelectObject(DC,OldFont);
  499.   Deleteobject(Font);
  500. end;
  501.  
  502. begin
  503. end.
  504.